using System;
using System.IO;
using QQZiFramework;
using System.Data;
using QQZiFramework.Membership;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using log4net;
using QQZiFramework.Modals;

namespace TestProject1
{
    public class OEMMemberShip : HandlerMemberShip
    {
        static List<OEMMemberShip> membershipList = new List<OEMMemberShip>();

        /// <summary>
        /// OEM商列表
        /// </summary>
        public static List<QQZiFramework.Modals.OEMInfo> OEMList { get { return OEMConfigs; } }
        protected static List<QQZiFramework.Modals.OEMInfo> OEMConfigs;

        public static OEMInfo GetOEM(string name)
        {
            return OEMList.Find(x => x.Name == name);
        }
        public override DBContext CreateDBContext()
        {
            System.Collections.Hashtable args = new System.Collections.Hashtable();
            args.Add("HttpContext", null);
            args.Add("OEMInfo", this.OEM);
            args.Add("IsMobileDevice", false);
            args.Add("IP", "127.0.0.1");
            return new DBContext(this.OEM.ProviderName, this.OEM.GetConnectionString(), null, this, args);

        }

        public static OEMMemberShip GetInstance(string oem)
        {
            if (membershipList == null) throw new Exception("Init please !");
            OEMMemberShip memberShip = membershipList.Find(X => X.OEM.Name.ToLower() == oem.ToLower());
            if (memberShip == null)
            {
                memberShip = new OEMMemberShip();
                OEMInfo oemInfo = GetOEM(oem);
                if (oemInfo == null) throw new Exception("没有找到该OEM对方的MemberShip，请在Startup初始化！");
                memberShip.SetOEM(oemInfo);
                membershipList.Add(memberShip);
            }
            return memberShip;
        }

        public static void GetOEMList()
        {
            OEMConfigs = new List<OEMInfo>();
            Newtonsoft.Json.Linq.JToken section = OEMProgram.appSettingJToken["OEMSetting"];
            foreach (Newtonsoft.Json.Linq.JProperty oemItem in section)
            {
                QQZiFramework.Modals.OEMInfo oem = new OEMInfo() { Name = oemItem.Name.ToUpper() };
                Newtonsoft.Json.Linq.JToken jToken = oemItem.Value;
                oem.ConnectionStr = jToken.Value<string>("Connection");
                oem.ExtName = jToken.Value<string>("ExtName");
                if (oem.ExtName == null) oem.ExtName = oem.Name;
                oem.Title = jToken.Value<string>("Title");
                oem.ProviderName = jToken.Value<string>("ProviderName");
                OEMConfigs.Add(oem);
            }

        }


        bool removePrefix;
        public static void Init(DBContext context)
        {
            GetOEMList();
            membershipList = new List<OEMMemberShip>();

            //BaseBusiness.Init(context, Path.Combine(rootPath, "wwwroot"));
            foreach (OEMInfo oem in OEMList)
            {
                if (oem.ExtName == null) oem.ExtName = oem.Name;
                LoadOEMConfig(context, oem);

                bool temp_removePrefix;
                oem.AppSetting.TryGetValue<bool>("RedisKeyRemovePrefix", out temp_removePrefix);
                OEMMemberShip membership = new OEMMemberShip();
                membership.SetOEM(oem);
                membershipList.Add(membership);
                membership.removePrefix = temp_removePrefix;
                string logConfigPath = Path.Combine(rootPath, "settings", oem.Name + ".log4net.config");
                FileInfo logFile = new FileInfo(logConfigPath);
                if (!logFile.Exists)
                {
                    logConfigPath = Path.Combine(rootPath, "log4net.config");
                    logFile = new FileInfo(logConfigPath);
                    System.Diagnostics.Debug.WriteLine(oem.Name + "没有对应的日志配置文件，使用默认的log4net.config");
                }
                if (logFile.Exists)
                {
                    string name = oem.Name + "_Repository";
                    var repository = LogManager.CreateRepository(name);
                    log4net.Config.XmlConfigurator.Configure(repository, logFile);
                }
                else
                {
                    throw new FileNotFoundException(logFile.FullName);
                }
                if (DBContext.UserRedis)
                {
                    using (DBContext oemContext = membership.CreateDBContext())
                    {
                        if (!oemContext.GetDBAccess().IsTableExists("A1_Configs")) continue;
                        //数据库参数配置
                        oemContext.GetRedisDatabase().DeleteRedisItem("system_config");
                        List<ConfigParam> lst = oemContext.QueryManySql<ConfigParam>("select * from A1_Configs");
                        foreach (ConfigParam configParam in lst)
                        {
                            oemContext.GetRedisDatabase().SetHashItem("system_config", configParam.ParamName, configParam);
                        }
                    }

                }

            }
        }
        public static void LoadOEMConfig(DBContext context, OEMInfo oem)
        {
            context.LogMessage("加载" + oem.Name + "配置", "Init");
            string jsonfile = Path.Combine(rootPath, "settings", oem.Name + ".json");
            if (File.Exists(jsonfile))
            {
                using (System.IO.StreamReader file = new StreamReader(jsonfile, System.Text.Encoding.UTF8))
                {
                    string json = file.ReadToEnd();
                    oem.AppSetting = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.Linq.JToken.Parse(json);
                }
            }
            else
            {
                context.LogMessage(oem.Name + "没有配置文件", "Init");
            }


        }


        OEMInfo oemInfo;

        public OEMInfo OEM { get { return oemInfo; } }

        private void SetOEM(OEMInfo oem)
        {
            oemInfo = oem;
        }

        #region IMembership

        public OEMMemberShip() : base()
        {

        }
        static Dictionary<string, Dictionary<string, QueryEntityConfig>> oemQueryMappings = new Dictionary<string, Dictionary<string, QueryEntityConfig>>();
        static Dictionary<string, Dictionary<string, QueryEntityConfig>> AdminOemQueryMappings = new Dictionary<string, Dictionary<string, QueryEntityConfig>>();

        private static Dictionary<string, QueryEntityConfig> appQueryMapping = null, AdminqueryMapping = null;

        /// <summary>
        /// Permission文件的内容
        /// </summary>  
        public override Dictionary<string, QueryEntityConfig> GetPermissionQueryMapping(DBContext context)
        {
            if (appQueryMapping == null || AdminqueryMapping == null)
            {
                appQueryMapping = LoadPermissionFile("Permission.json");
                AdminqueryMapping = LoadPermissionFile("Permission.Admin.json");
            }

            Dictionary<string, Dictionary<string, QueryEntityConfig>> whichDic;
            Dictionary<string, QueryEntityConfig> defaultMapping;
            string PermissionFileFirst = "Permission.";
            if (context.GetArgument<string>("Route-DATA-AREA") == "Admin")
            {
                PermissionFileFirst = "Permission.Admin.";
                whichDic = AdminOemQueryMappings;
                defaultMapping = AdminqueryMapping;
            }
            else
            {
                whichDic = oemQueryMappings;
                defaultMapping = appQueryMapping;
            }
            if (context.OEM == null) throw new Exception("OEM不正确");
            lock (whichDic)
            {
                if (whichDic.ContainsKey(context.OEM.Name)) return whichDic[context.OEM.Name];

                Dictionary<string, QueryEntityConfig> queryMapping = LoadPermissionFile(PermissionFileFirst + context.OEM.ExtName + ".json");
                //添加公共的Permission.json
                foreach (KeyValuePair<string, QueryEntityConfig> kv in defaultMapping)
                {
                    if (!queryMapping.ContainsKey(kv.Key)) queryMapping.Add(kv.Key, kv.Value);
                }
                whichDic.Add(context.OEM.Name, queryMapping);
                return queryMapping;
            }
        }

        private Dictionary<string, QueryEntityConfig> LoadPermissionFile(string fileName)
        {
            String filePath = Path.Combine(rootPath, fileName);
            if (File.Exists(filePath))
            {
                string json = QQZiFramework.Utility.ReadFile(filePath);
                if (string.IsNullOrEmpty(json)) return new Dictionary<string, QueryEntityConfig>();
                else return Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, QueryEntityConfig>>(json);
            }
            else return new Dictionary<string, QueryEntityConfig>();
        }

        /// <summary>
        /// 读取获取设置Redis缓存Key
        /// </summary>
        /// <returns>处理后的key</returns>
        public override string OnRedisKey(string key)
        {
            if (oemInfo == null || removePrefix) return key;
            return oemInfo.Name + "_" + key;
        }

        /// <summary>
        /// 读取获取设置系统缓存Key
        /// </summary>
        /// <returns>处理后的key</returns>
        public override string OnCacheKey(string key)
        {
            if (oemInfo == null) throw new QQZiFramework.NotAlowAccessException();
            return oemInfo.Name + "_" + key;
        }


        public override T GetSettingValue<T>(DBContext context, string path, bool throwNoFoundError = false, T defaultVal = default(T))
        {
            if (OEM == null) throw new ClientException("OEM为空，请确认继承QQZiCore.Mvc.Controllers.BaseController并使用CreateDBContext创建DBContext");
            if (DBContext.UserRedis)
            {
                ConfigParam configParam = context.GetRedisDatabase().GetHashItem<ConfigParam>("system_config", path, false);
                string val = null;
                if (configParam != null) val = configParam.ParamValue;
                if (val != null)
                {
                    return (T)Convert.ChangeType(val, typeof(T));
                }
            }
            T t;
            if (OEM.AppSetting.TryGetValue(path, out t))
            {
                return t;
            }
            else return base.GetSettingValue<T>(context, path, throwNoFoundError, defaultVal);
        }

        #endregion
    }

}